package impl;

import anaydis.sort.SorterType;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
import java.util.List;

public class InsertionSorter extends AbstractSorter{

    public InsertionSorter(){
        super(SorterType.INSERTION);
    }

    @NotNull
    public SorterType getType(){
        return SorterType.INSERTION;
    }

    //sort Ordena el arreglo pasado como parametro

    public <T> void sort(Comparator<T> tComparator, List<T> ts){
        for(int i=0; i<ts.size()-1; i++){
            if(greater(tComparator, ts, i/2,i+1)){   //compara el elemento del medio con el nuevo a agregar
                swap(ts, i/2, i+1);    //al ser mayor, lo coloca en el medio y guarda en auxiliar el del medio valor
                int temp = i/2;                      //posiciona un foco temporal en el medio del arreglo
                while(temp < i+1){                   //este while reordena todos los elementos mayores al del medio
                    temp++;
                    swap(ts, temp, i+1);
                }
                temp = i/2;
                boolean cond = true;
                while(temp>0 && cond){
                    if(greater(tComparator, ts, temp, temp-1)){
                        cond = false;
                    }
                    else{
                        swap(ts, temp, temp-1);
                        temp--;
                    }
                }

            }else{

                int temp = (i/2)+1;
                while(temp<i+1){

                    if(greater(tComparator, ts, i+1, temp)){
                        temp++;
                    }
                    else{
                        swap(ts, temp, i+1);
                        temp++;
                    }
                }
            }
        }

    }

    //Ordena los elementos del arreglo en el intervalo
    // pasado por los parametros desde - hasta
    
    public <T> void sort(Comparator<T> tComparator, List<T> ts, int desde, int hasta){
        for(int i=desde; i<hasta-1; i++){
            if(greater(tComparator, ts, i/2,i+1)){   //compara el elemento del medio con el nuevo a agregar
                swap(ts, i/2, i+1);    //al ser mayor, lo coloca en el medio y guarda en auxiliar el del medio valor
                int temp = i/2;                      //posiciona un foco temporal en el medio del arreglo
                while(temp < i+1){                   //este while reordena todos los elementos mayores al del medio
                    temp++;
                    swap(ts, temp, i+1);
                }
                temp = i/2;
                boolean cond = true;
                while(temp>0 && cond){
                    if(greater(tComparator, ts, temp, temp-1)){
                        cond = false;
                    }
                    else{
                        swap(ts, temp, temp-1);
                        temp--;
                    }
                }

            }else{

                int temp = (i/2)+1;
                while(temp<i+1){

                    if(greater(tComparator, ts, i+1, temp)){
                        temp++;
                    }
                    else{
                        swap(ts, temp, i+1);
                        temp++;
                    }
                }
            }
        }

    }
}
